<template>
  <a-modal class="image-cropper" :open="visible" title="编辑图片" :footer="false" @cancel="closeModal">
    <vue-cropper
      ref="cropperRef"
      :img="imageUrl"
      :autoCrop="true"
      :fixedBox="false"
      :centerBox="true"
      :canMoveBox="true"
      :info="true"
      outputType="png"
    />
    <div style="margin-bottom: 16px" />
    <!-- 图片操作 -->
    <div class="image-cropper-actions">
      <a-space>
        <a-button @click="rotateLeft" :disabled="!canEdit">向左旋转</a-button>
        <a-button @click="rotateRight" :disabled="!canEdit">向右旋转</a-button>
        <a-button @click="changeScale(1)" :disabled="!canEdit">放大</a-button>
        <a-button @click="changeScale(-1)" :disabled="!canEdit">缩小</a-button>
        <a-button type="primary" :loading="loading" :disabled="!canEdit" @click="handleConfirm">
          确认
        </a-button>
      </a-space>
    </div>
    <!-- 协同编辑操作 -->
    <div class="image-edit-actions" v-if="isTeamSpace">
      <a-space>
        <a-button v-if="editingUser" disabled> {{ editingUser.userName }}正在编辑</a-button>
        <a-button v-if="canEnterEdit" type="primary" ghost @click="enterEdit">进入编辑</a-button>
        <a-button v-if="canExitEdit" danger ghost @click="exitEdit">退出编辑</a-button>
      </a-space>
    </div>
  </a-modal>
</template>

<script setup lang="ts">
import { computed, onUnmounted, ref, watch } from 'vue'
import { message } from 'ant-design-vue'
import { uploadPictureUsingPost } from '@/api/pictureController.ts'
import { useLoginUserStore } from '@/stores/useLoginUserStore.ts'
import PictureEditWebSocket from '@/utils/websocketUtil.ts'
import { PICTURE_EDIT_MESSAGE_TYPE_ENUM, PICTURE_EDIT_ACTION_ENUM } from '@/constants/picture.ts'
import { SPACE_TYPE_ENUM } from '@/constants/space-permission.ts'

interface Props {
  imageUrl?: string
  picture?: API.PictureVO
  spaceId?: number
  space?: API.SpaceVO,
  onSuccess?: (newPicture: API.PictureVO) => void
}

const props = defineProps<Props>()
// 编辑器组件的引用
const cropperRef = ref()

const loading = ref<boolean>(false)

// 是否可见
const visible = ref(false)

// 打开弹窗
const openModal = () => {
  visible.value = true
}

// 暴露函数给父组件
defineExpose({
  openModal
})

// --------- 实时编辑 ---------
const loginUserStore = useLoginUserStore()
const loginUser = loginUserStore.loginUser
// 正在编辑的用户
const editingUser = ref<API.UserVO>()
// 用户是否正在尝试编辑（本地状态）
const isEditing = ref(false)
// 已知用户信息映射 (userId -> userName)
const knownUsers = ref<Record<string, string>>({})
// 没有用户正在编辑中，可进入编辑
const canEnterEdit = computed(() => {
  return !editingUser.value
})
// 正在编辑的用户是本人，可退出编辑
const canExitEdit = computed(() => {
  return editingUser.value?.id === loginUser.id || isEditing.value
})
// 可以编辑
const canEdit = computed(() => {
  // 不是团队空间，则默认可编辑
  if (!isTeamSpace.value) {
    return true
  }
  // 用户自己请求了编辑权限
  if (isEditing.value) {
    return true
  }
  // 没有人在编辑时也可以操作
  if (!editingUser.value) {
    return true
  }
  // 只有当前编辑用户可以操作
  return editingUser.value?.id === loginUser.id
})

let websocket: PictureEditWebSocket | null

// 初始化 WebSocket 连接，绑定事件
const initWebsocket = () => {
  const pictureId = props.picture?.id
  if (!pictureId) {
    return
  }

  // 防止之前的连接未释放
  if (websocket) {
    websocket.disconnect()
  }

  // 创建 WebSocket 实例
  websocket = new PictureEditWebSocket(pictureId)
  // 建立 WebSocket 连接
  websocket.connect()

  // 监听通知消息
  websocket.on(PICTURE_EDIT_MESSAGE_TYPE_ENUM.INFO, (msg) => {
    console.log('收到通知消息：', msg)
    message.info(msg.message)
  })

  // 监听错误消息
  websocket.on(PICTURE_EDIT_MESSAGE_TYPE_ENUM.ERROR, (msg) => {
    console.log('收到错误消息：', msg)
    message.error(msg.message)
  })

  // 监听进入编辑状态消息
  websocket.on(PICTURE_EDIT_MESSAGE_TYPE_ENUM.ENTER_EDIT, (msg) => {
    console.log('收到进入编辑状态消息：', msg)
    message.info(msg.message)
    // 更新当前编辑用户
    editingUser.value = {
      id: msg.userId,
      userName: msg.userName
    }
    // 保存用户信息到映射中
    knownUsers.value[msg.userId] = msg.userName
    // 如果是自己进入编辑状态，更新本地编辑状态
    if (msg.userId === loginUser.id) {
      isEditing.value = true
    }
  })

  // 监听编辑操作消息
  websocket.on(PICTURE_EDIT_MESSAGE_TYPE_ENUM.EDIT_ACTION, (msg) => {
    console.log('收到编辑操作消息：', msg)
    // 只处理其他用户的操作
    if (msg.user?.userId !== loginUser.id) {
      // 优先使用消息中的用户名，其次从已知用户中获取，最后使用默认值
      const userName = msg.user?.userName || knownUsers.value[msg.user?.userId] || '未知用户'
      message.info(`${userName}执行了操作: ${msg.editAction}`)
      switch (msg.editAction) {
        case PICTURE_EDIT_ACTION_ENUM.ROTATE_LEFT:
          cropperRef.value.rotateLeft()
          break
        case PICTURE_EDIT_ACTION_ENUM.ROTATE_RIGHT:
          cropperRef.value.rotateRight()
          break
        case PICTURE_EDIT_ACTION_ENUM.ZOOM_IN:
          cropperRef.value.changeScale(1)
          break
        case PICTURE_EDIT_ACTION_ENUM.ZOOM_OUT:
          cropperRef.value.changeScale(-1)
          break
      }
    }
  })

  // 监听退出编辑状态消息
  websocket.on(PICTURE_EDIT_MESSAGE_TYPE_ENUM.EXIT_EDIT, (msg) => {
    console.log('收到退出编辑状态消息：', msg)
    message.info(msg.message)
    // 清除当前编辑用户
    editingUser.value = undefined
    // 如果是自己退出编辑状态，更新本地编辑状态
    if (msg.userId === loginUser.id) {
      isEditing.value = false
    }
  })
}

// 监听 visible 变化来初始化 WebSocket
watch(visible, (newVal) => {
  if (newVal) {
    // 延迟初始化以确保组件已完全渲染
    setTimeout(() => {
      if (isTeamSpace.value) {
        initWebsocket()
      }
    }, 100)
  } else {
    // 关闭时断开连接
    if (websocket) {
      websocket.disconnect()
      websocket = null
    }
    editingUser.value = undefined
    isEditing.value = false
    // 清空已知用户信息
    knownUsers.value = {}
  }
})

onUnmounted(() => {
  // 断开连接
  if (websocket) {
    websocket.disconnect()
  }
  editingUser.value = undefined
  isEditing.value = false
  knownUsers.value = {}
})

// 关闭弹窗
const closeModal = () => {
  visible.value = false
}

// 进入编辑状态
const enterEdit = () => {
  if (websocket) {
    // 发送进入编辑状态的消息
    websocket.sendMessage({
      type: PICTURE_EDIT_MESSAGE_TYPE_ENUM.ENTER_EDIT,
      userId: loginUser.id,
      userName: loginUser.userName,
      message: `${loginUser.userName}进入编辑状态`
    })
    // 本地也更新状态，提供即时反馈
    editingUser.value = {
      id: loginUser.id,
      userName: loginUser.userName
    }
    // 保存到已知用户映射
    knownUsers.value[loginUser.id] = loginUser.userName
    isEditing.value = true
  }
}

// 退出编辑状态
const exitEdit = () => {
  if (websocket) {
    // 发送退出编辑状态的消息
    websocket.sendMessage({
      type: PICTURE_EDIT_MESSAGE_TYPE_ENUM.EXIT_EDIT,
      userId: loginUser.id,
      userName: loginUser.userName,
      message: `${loginUser.userName}退出编辑状态`
    })
    // 本地也更新状态
    editingUser.value = undefined
    isEditing.value = false
  }
}

// 编辑图片操作
const editAction = (action: string) => {
  if (websocket && canEdit.value) {
    // 发送编辑操作的请求
    websocket.sendMessage({
      type: PICTURE_EDIT_MESSAGE_TYPE_ENUM.EDIT_ACTION,
      editAction: action,
      userId: loginUser.id,
      userName: loginUser.userName,
      message: `${loginUser.userName}执行了${action}操作`
    })
  } else if (!canEdit.value) {
    message.warning('暂无编辑权限')
  }
}

// 向左旋转
const rotateLeft = () => {
  if (canEdit.value) {
    cropperRef.value.rotateLeft()
    editAction(PICTURE_EDIT_ACTION_ENUM.ROTATE_LEFT)
  } else {
    message.warning('暂无编辑权限')
  }
}

// 向右旋转
const rotateRight = () => {
  if (canEdit.value) {
    cropperRef.value.rotateRight()
    editAction(PICTURE_EDIT_ACTION_ENUM.ROTATE_RIGHT)
  } else {
    message.warning('暂无编辑权限')
  }
}

// 缩放
const changeScale = (num: number) => {
  if (canEdit.value) {
    cropperRef.value.changeScale(num)
    if (num > 0) {
      editAction(PICTURE_EDIT_ACTION_ENUM.ZOOM_IN)
    } else {
      editAction(PICTURE_EDIT_ACTION_ENUM.ZOOM_OUT)
    }
  } else {
    message.warning('暂无编辑权限')
  }
}

// 确认裁剪
const handleConfirm = () => {
  cropperRef.value.getCropBlob((blob: Blob) => {
    const fileName = (props.picture?.name || 'image') + '.png'
    const file = new File([blob], fileName, { type: blob.type })
    // 上传图片
    handleUpload({ file })
  })
}

/**
 * 上传
 * @param file
 */
const handleUpload = async ({ file }: any) => {
  loading.value = true
  try {
    const params: API.PictureUploadRequestDTO = props.picture ? { id: props.picture.id } : {}
    params.spaceId = props.spaceId
    const res = await uploadPictureUsingPost(params, {}, file)
    if (res.data.code === 0 && res.data.data) {
      message.success('图片上传成功')
      // 将上传成功的图片信息传递给父组件
      props.onSuccess?.(res.data.data)
      closeModal()
    } else {
      message.error('图片上传失败，' + res.data.message)
    }
  } catch (error) {
    message.error('图片上传失败')
  } finally {
    loading.value = false
  }
}

// 是否为团队空间
const isTeamSpace = computed(() => {
  return props.space?.spaceType === SPACE_TYPE_ENUM.TEAM
})
</script>

<style scoped>
.image-cropper {
  text-align: center;
}

.image-cropper .vue-cropper {
  height: 400px;
}
</style>
